﻿using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace CaseManagerLibrary.Encrypt
{
    public static class EncryptKit
    {
        public static string EncryptPassword(string password, string salt)
        {
            using (var sha256 = SHA256.Create())
            {
                var saltedPassword = string.Format("{0}{1}", salt, password);
                byte[] saltedPasswordAsBytes = Encoding.UTF8.GetBytes(saltedPassword);
                return Convert.ToBase64String(sha256.ComputeHash(saltedPasswordAsBytes));
            }
        }

        #region string ToLowerMd5(string value) MD5加密(小写)
        /// <summary>
        ///  MD5加密(小写)
        /// </summary>
        /// <param name="value">被加密字符串</param>
        /// <returns></returns>
        public static string ToLowerMd5(string value)
        {
            byte[] bytes = Encoding.Default.GetBytes(value);
            using (var provider = new MD5CryptoServiceProvider())
            {
                bytes = provider.ComputeHash(bytes);
                StringBuilder stringBuilder = new StringBuilder(bytes.Length * 2);
                foreach (byte data in bytes)
                {
                    stringBuilder.Append(data.ToString("x").PadLeft(2, '0'));
                }
                return stringBuilder.ToString();
            }
        }

        #endregion

        #region string ToUpperMd5(string value) MD5加密(大写)
        /// <summary>
        ///  MD5加密(大写)
        /// </summary>
        /// <param name="value">被加密字符串</param>
        /// <returns></returns>
        public static string ToUpperMd5(string value)
        {
            byte[] bytes = Encoding.Default.GetBytes(value);
            using (var provider = new MD5CryptoServiceProvider())
            {
                bytes = provider.ComputeHash(bytes);
                StringBuilder stringBuilder = new StringBuilder(bytes.Length * 2);
                foreach (byte data in bytes)
                {
                    stringBuilder.Append(data.ToString("X").PadLeft(2, '0'));
                }
                return stringBuilder.ToString();
            }

        }
        #endregion

        #region ToSHA256 SHA256加密
        /// <summary>
        /// SHA256加密
        /// </summary>
        /// <param name="targetString">原始字符串</param>
        /// <returns>加密后字符串</returns>
        public static string ToSHA256(string targetString)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(targetString);
            using (var managed = new SHA256Managed())
            {
                byte[] result = managed.ComputeHash(bytes);
                return Convert.ToBase64String(result);  //返回长度为44字节的字符串
            }
        }
        #endregion

        #region Base64 加解密
        ///// <summary>
        ///// 进行 Base64 加密
        ///// </summary>
        ///// <param name="value">被加密字符串</param>
        ///// <returns></returns>
        //public static string EncodeBase64(string value)
        //{
        //    return Convert.ToBase64String(Encoding.UTF8.GetBytes(value));
        //}

        ///// <summary>
        ///// 进行 Base64 解密
        ///// </summary>
        ///// <param name="value">被解密字符串</param>
        ///// <returns></returns>
        //public static string DecodeBase64(string value)
        //{
        //    return Encoding.UTF8.GetString(Convert.FromBase64String(value));
        //}

        /// <summary>
        /// 转换成Base64编码的字符集
        /// </summary>
        private const string BASE64CHR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        /// <summary>
        /// 转换成64编码的字符集数组
        /// </summary>
        private static string[] psBase64Chr = new string[64];


        /// <summary>
        /// 把一个经过Base64编码的字符串中解码成字符串
        /// </summary>
        /// <param name="str2Decode">Base64编码的字符串</param>
        /// <returns>解码出来的字符串</returns>
        public static string DecodeBase64String(string str2Decode, System.Text.Encoding encode)
        {
            return encode.GetString(DecodeBase64Byte(str2Decode));
        }
        /// <summary>
        /// 把一个经过Base64编码的字符串中解码成字节数组
        /// </summary>
        /// <param name="str2Decode">Base64编码的字符串</param>
        /// <returns>解码出来的字节数组</returns>
        public static byte[] DecodeBase64Byte(string str2Decode)
        {
            long lPtr = 0;
            int iValue = 0;
            int iLen = 0;
            int iCtr = 0;
            byte[] Bits = new byte[4];
            string str = null;
            byte[] Output = new byte[1];

            long iIndex = 0;

            long lFrom = 0;
            long lTo = 0;

            InitBase();


            ////除去回车
            str = Strings.Replace(str2Decode, Constants.vbCrLf, "", 1, -1, CompareMethod.Text);

            ////每4个字符一组（4个字符表示3个字）
            for (lPtr = 1; lPtr <= Strings.Len(str); lPtr += 4)
            {
                iLen = 4;
                for (iCtr = 0; iCtr <= 3; iCtr++)
                {
                    ////查找字符在BASE64字符串中的位置
                    iValue = Strings.InStr(1, BASE64CHR, Strings.Mid(str, Convert.ToInt32(lPtr + iCtr), 1), Constants.vbBinaryCompare);

                    if (iValue > 0 && iValue < 65)
                    {
                        Bits[iCtr] = Convert.ToByte(iValue - 1);
                    }
                    else if (iValue == 65)
                    {
                        iLen = iCtr;
                        break;
                    }
                    else
                    {
                        return Output;
                    }
                }

                ////转换4个6比特数成为3个8比特数
                Bits[0] = Convert.ToByte(Bits[0] * 0x4 + (Bits[1] & 0x30) / 0x10);
                Bits[1] = Convert.ToByte((Bits[1] & 0xf) * 0x10 + (Bits[2] & 0x3c) / 0x4);
                Bits[2] = Convert.ToByte((Bits[2] & 0x3) * 0x40 + Bits[3]);

                ////计算数组的起始位置
                lFrom = lTo;
                lTo = lTo + (iLen - 1) - 1;

                ////重新定义输出数组
                Array.Resize(ref Output, Convert.ToInt32(lTo + 1));

                for (iIndex = lFrom; iIndex <= lTo; iIndex++)
                {
                    Output[iIndex] = Bits[iIndex - lFrom];
                }

                lTo = lTo + 1;

            }
            return Output;
        }
        /// <summary>
        /// 将一个字节数组进行Base64编码,返回为编码后的字符串
        /// </summary>
        /// <param name="sValue">一个字节数组byte[]</param>
        /// <returns>编码后的字符串</returns>
        public static string EncodeBase64Byte(byte[] sValue)
        {
            long lCtr = 0;
            long lPtr = 0;
            long lLen = 0;
            string sEncoded = null;
            byte[] Bits8 = new byte[3];
            byte[] Bits6 = new byte[4];

            int i = 0;

            InitBase();
            sEncoded = string.Empty;


            for (lCtr = 1; lCtr <= Information.UBound(sValue, 1) + 1; lCtr += 3)
            {
                for (i = 1; i <= 3; i++)
                {
                    if (lCtr + i - 2 <= Information.UBound(sValue, 1))
                    {
                        Bits8[i - 1] = sValue[lCtr + i - 2];
                        lLen = 3;
                    }
                    else
                    {
                        Bits8[i - 1] = 0;
                        lLen = lLen - 1;
                    }
                }

                ////转换字符串为数组，然后转换为4个6位(0-63)
                Bits6[0] = Convert.ToByte((Bits8[0] & 0xfc) / 4);
                Bits6[1] = Convert.ToByte((Bits8[0] & 0x3) * 0x10 + (Bits8[1] & 0xf0) / 0x10);
                Bits6[2] = Convert.ToByte((Bits8[1] & 0xf) * 4 + (Bits8[2] & 0xc0) / 0x40);
                Bits6[3] = Convert.ToByte(Bits8[2] & 0x3f);

                ////添加4个新字符
                for (lPtr = 1; lPtr <= lLen + 1; lPtr++)
                {
                    sEncoded = sEncoded + psBase64Chr[Convert.ToInt32(Bits6[lPtr - 1])];
                }
            }

            ////不足4位，以=填充
            switch (lLen + 1)
            {
                case 2:
                    sEncoded = sEncoded + "==";
                    break;
                case 3:
                    sEncoded = sEncoded + "=";
                    break;
                case 4:
                    break;
            }

            return sEncoded;
        }
        /// <summary>
        /// 将一个字符串进行Base64编码,返回为字符串
        /// </summary>
        /// <param name="str2Encode">一个字符串</param>
        /// <returns>编码后的字符串</returns>
        public static string EncodeBase64String(string str2Encode)
        {
            byte[] sValue = null;
            sValue = Encoding.Default.GetBytes(str2Encode);
            return EncodeBase64Byte(sValue);
        }

        /// <summary>
        /// 初始化字节数组
        /// </summary>
        private static void InitBase()
        {
            int iPtr = 0;
            //初始化 BASE64数组
            for (iPtr = 0; iPtr <= 63; iPtr++)
            {
                psBase64Chr[iPtr] = Strings.Mid(BASE64CHR, iPtr + 1, 1);
            }
        }
        #endregion


        #region AES加解密

        //默认密钥向量
        private static readonly byte[] AESKeys = { 0x41, 0x72, 0x65, 0x79, 0x6F, 0x75, 0x6D, 0x79, 0x53, 0x6E, 0x6F, 0x77, 0x6D, 0x61, 0x6E, 0x3F };

        public static string AESEncode(string encryptString, string encryptKey)
        {
            encryptKey = StringKit.CutString(encryptKey, 32, string.Empty);
            encryptKey = encryptKey.PadRight(32, ' ');

            using (var managed = new RijndaelManaged { Key = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 32)), IV = AESKeys })
            using (var transform = managed.CreateEncryptor())
            {
                byte[] inputDatas = Encoding.UTF8.GetBytes(encryptString);
                byte[] encryptedData = transform.TransformFinalBlock(inputDatas, 0, inputDatas.Length);
                return Convert.ToBase64String(encryptedData);
            }

        }

        public static string AESDecode(string decryptString, string decryptKey)
        {
            try
            {
                decryptKey = StringKit.CutString(decryptKey, 32, string.Empty);
                decryptKey = decryptKey.PadRight(32, ' ');

                using (var managed = new RijndaelManaged { Key = Encoding.UTF8.GetBytes(decryptKey), IV = AESKeys })
                using (var transform = managed.CreateDecryptor())
                {
                    byte[] inputDatas = Convert.FromBase64String(decryptString);
                    byte[] decryptedData = transform.TransformFinalBlock(inputDatas, 0, inputDatas.Length);
                    return Encoding.UTF8.GetString(decryptedData);
                }
            }
            catch
            {
                return string.Empty;
            }

        }

        #endregion

        #region DES加解密

        //默认密钥向量
        private static readonly byte[] DESKeys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

        /// <summary>
        /// DES默认密钥
        /// </summary>
        private const string DESDefaultKey = "jxsyxxly";

        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <param name="encryptKey">加密密钥,要求为8位</param>
        /// <returns></returns>
        public static string DESEncode(string encryptString, string encryptKey)
        {
            encryptKey = StringKit.CutString(encryptKey, 8, string.Empty);
            encryptKey = encryptKey.PadRight(8, '#');

            byte[] customizedKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
            byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);

            using (var serviceProvider = new DESCryptoServiceProvider())
            using (var stream = new MemoryStream())
            using (var cryptoStream = new CryptoStream(stream, serviceProvider.CreateEncryptor(customizedKey, DESKeys), CryptoStreamMode.Write))
            {
                cryptoStream.Write(inputByteArray, 0, inputByteArray.Length);
                cryptoStream.FlushFinalBlock();
                return Convert.ToBase64String(stream.ToArray());
            }
        }

        /// <summary>
        /// DES加密（调用类库中默认密钥）
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <returns></returns>
        public static string DESEncode(string encryptString)
        {
            return DESEncode(encryptString, DESDefaultKey);
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="decryptString">待解密的字符串</param>
        /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
        /// <returns></returns>
        public static string DESDecode(string decryptString, string decryptKey)
        {
            decryptKey = StringKit.CutString(decryptKey, 8, string.Empty);
            decryptKey = decryptKey.PadRight(8, '#');

            byte[] customizedKey = Encoding.UTF8.GetBytes(decryptKey);
            byte[] inputByteArray = Convert.FromBase64String(decryptString);

            using (var serviceProvider = new DESCryptoServiceProvider())
            using (var stream = new MemoryStream())
            using (var cryptoStream = new CryptoStream(stream, serviceProvider.CreateDecryptor(customizedKey, DESKeys), CryptoStreamMode.Write))
            {
                cryptoStream.Write(inputByteArray, 0, inputByteArray.Length);
                cryptoStream.FlushFinalBlock();
                return Encoding.UTF8.GetString(stream.ToArray());
            }
        }

        /// <summary>
        /// DES解密（调用系统默认密钥解密）
        /// </summary>
        /// <param name="decryptString">待解密的字符串</param>
        /// <returns></returns>
        public static string DESDecode(string decryptString)
        {
            return DESDecode(decryptString, DESDefaultKey);
        }

        #endregion

    }
}

